﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Http;
using Common.Logging;
using In.Api.Dto.HisWs;
using Newtonsoft.Json;
using Out.Service.HttpClients;
using OutDbContext;

namespace Out.Service.Services
{
    public class BizHospCard : IDisposable
    {
        /// <summary>
        /// 就诊卡类型
        /// </summary>
        public enum CardType
        {
            诊疗卡 = 0,
            健康卡 = 1,
            市民卡 = 2,
            员工卡 = 3
        }

        private static readonly ILog Logger = LogManager.GetLogger(typeof(BizHospCard));
        private readonly GdsfybjyWeiXinEntities _ctx;
        private readonly string _openId;
        private int _cardId;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="openId">用户openid</param>
        public BizHospCard(string openId = "")
        {
            _openId = openId;
            _ctx = new GdsfybjyWeiXinEntities();
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="cardId">就诊卡Id</param>
        /// <param name="openId">用户openid</param>
        public BizHospCard(int cardId, string openId = "")
        {
            _cardId = cardId;
            _openId = openId;
            _ctx = new GdsfybjyWeiXinEntities();
        }

        /// <summary>
        /// 获取就诊卡
        /// </summary>
        /// <returns></returns>
        public HospCard Get()
        {
            var card = _ctx.HospCards.IsOpenId(_openId).FirstOrDefault(x => x.CardId == _cardId);
            return card;
        }

        /// <summary>
        /// 获取用户所有就诊卡
        /// </summary>
        /// <returns></returns>
        public List<HospCard> GetAll()
        {
            var cards = _ctx.HospCards.IsOpenId(_openId).Where(x => x.CardStatus == 1 && x.DeleteStatus == 0)
                .OrderByDescending(x => x.IsDefault).ThenBy(x => x.CardNo).ToList();
            return cards;
        }

        /// <summary>
        /// 获取用户的默认就诊卡
        /// </summary>
        /// <returns></returns>
        public HospCard GetDefault()
        {
            var card = _ctx.HospCards.IsOpenId(_openId)
                .FirstOrDefault(x => x.CardStatus == 1 && x.DeleteStatus == 0 && x.IsDefault == 1);
            return card;
        }

        /// <summary>
        /// 得到用户最后绑定的就诊卡
        /// </summary>
        /// <param name="cardNo">就诊卡号</param>
        /// <param name="cardType">就诊卡类型</param>
        /// <returns></returns>
        public HospCard GetLastestCard(string cardNo,int cardType)
        {
            return _ctx.HospCards.Where(
            x => x.OpenId == _openId && x.CardNo == cardNo && x.CardType == cardType && x.CardStatus == 1 && x.DeleteStatus == 0).OrderByDescending(x => x.AddDt).FirstOrDefault();
        }

        /// <summary>
        /// 根据就诊卡号得到就诊卡信息
        /// </summary>
        /// <param name="cardNo">就诊卡号</param>
        /// <returns></returns>
        public HospCard GetCardByCardNo(string cardNo)
        {
            return _ctx.HospCards.OrderByDescending(x => x.AddDt).FirstOrDefault(x => x.OpenId == _openId && x.CardNo == cardNo );
        }

        /// <summary>
        /// 设置默认就诊卡
        /// </summary>
        public void SetDefault()
        {
            var cards = _ctx.HospCards.IsOpenId(_openId).ToList();
            foreach (var card in cards)
            {
                card.IsDefault = 0;
                if (card.CardId == _cardId)
                {
                    card.IsDefault = 1;
                }
            }
            _ctx.SaveChanges();
        }

        /// <summary>
        /// 删除就诊卡
        /// </summary>
        public void Delete()
        {
            var card = _ctx.HospCards.IsOpenId(_openId).FirstOrDefault(x => x.CardId == _cardId);
            if (card != null)
            {
                card.DeleteStatus = 1;
                card.DeleteDt = DateTime.Now;
                _ctx.SaveChanges();
            }

            var cards = _ctx.HospCards.IsOpenId(_openId)
                .Where(x => x.DeleteStatus == 0).OrderBy(x => x.CardNo).ToList();
            for (int i = 0; i < cards.Count; i++)
            {
                cards[i].IsDefault = i == 0 ? 1 : 0;
            }
            _ctx.SaveChanges();
        }

        /// <summary>
        /// 绑定新就诊卡
        /// </summary>
        /// <param name="cardType">卡类型</param>
        /// <param name="cardNo">卡号</param>
        /// <param name="cardName">姓名</param>
        /// <param name="setAsDefault">是否设置为默认卡</param>
        /// <returns></returns>
        public ResResult<HospCard> AddBindingCard(CardType cardType, string cardNo, string cardName, bool setAsDefault)
        {
            var cardMax = ConfigurationManager.AppSettings["CardMax"].ToInt32();
            var cardCount = _ctx.HospCards
                .IsOpenId(_openId).Count(x => x.CardStatus == 1 && x.DeleteStatus == 0);
            if (cardCount >= cardMax)
            {
                return new ResResult<HospCard>(Result.失败, "最多可以添加" + cardMax + "张就诊卡!");
            }

            if (cardCount == 0)
            {
                setAsDefault = true;
            }

            var intCardType = cardType.ToInt32();
            var card =
                _ctx.HospCards
                .FirstOrDefault(x => x.CardType == intCardType && x.CardNo == cardNo);
            if (card != null)
            {
                if (card.PatientName != cardName)
                {
                    return new ResResult<HospCard>(Result.失败, "操作失败，卡号与姓名不匹配");
                }
                if (card.OpenId == _openId)
                {
                    card.DeleteStatus = 0;
                    card.CardStatus = 1;
                    card.DeleteDt = null;
                    card.AddDt = DateTime.Now;
                    card.UpdateDt = DateTime.Now;

                    _ctx.SaveChanges();
                    _cardId = card.CardId;
                }
                else
                {
                    var newExistCard = new HospCard
                    {
                        OpenId = _openId,
                        CardType = cardType.ToInt32(),
                        CardNo = cardNo.Trim(),
                        PatientName = card.PatientName.Trim(),
                        CardStatus = 1,
                        AddDt = DateTime.Now,
                        UpdateDt = DateTime.Now,
                        DeleteStatus = 0,
                        PatientId = card.PatientId.Trim(),
                        InDeptNo = card.InDeptNo.Trim(),
                        Name = card.Name.Trim(),
                        Gender = card.Gender.Trim(),
                        Age = card.Age.Trim(),
                        Birthdate = card.Birthdate.Trim(),
                        IdenNo = card.IdenNo.Trim(),
                        Phone = card.Phone.Trim(),
                        FeeType = card.FeeType.Trim()
                    };

                    _ctx.HospCards.Add(newExistCard);
                    _ctx.SaveChanges();
                    _cardId = newExistCard.CardId;

                    card = newExistCard;
                }

                if (setAsDefault)
                {
                    SetDefault();
                }

                return new ResResult<HospCard>(Result.成功, card);
            }

            var getPatientInfoResult = GetPatientInfo(cardType, cardNo);
            if (getPatientInfoResult.Result == Result.未返回)
            {
                return new ResResult<HospCard>(Result.失败, "操作失败，请稍后重试");
            }
            if (getPatientInfoResult.Result == Result.失败)
            {
                return new ResResult<HospCard>(Result.失败, getPatientInfoResult.Message);
            }
            if (getPatientInfoResult.Response.PatientInfo.Name.Trim() != cardName.Trim())
            {
                return new ResResult<HospCard>(Result.失败, "操作失败，卡号与姓名不匹配");
            }

            var newCard = new HospCard
            {
                OpenId = _openId,
                CardType = cardType.ToInt32(),
                CardNo = cardNo.Trim(),
                PatientName = getPatientInfoResult.Response.PatientInfo.Name.Trim(),
                CardStatus = 1,
                AddDt = DateTime.Now,
                UpdateDt = DateTime.Now,
                DeleteStatus = 0,
                PatientId = getPatientInfoResult.Response.PatientInfo.PatientId.Trim(),
                InDeptNo = getPatientInfoResult.Response.PatientInfo.InDeptNo.Trim(),
                Name = getPatientInfoResult.Response.PatientInfo.Name.Trim(),
                Gender = getPatientInfoResult.Response.PatientInfo.Gender.Trim(),
                Age = getPatientInfoResult.Response.PatientInfo.Age.Trim(),
                Birthdate = getPatientInfoResult.Response.PatientInfo.Birthdate.Trim(),
                IdenNo = getPatientInfoResult.Response.PatientInfo.IdenNo.Trim(),
                Phone = getPatientInfoResult.Response.PatientInfo.Phone.Trim(),
                FeeType = getPatientInfoResult.Response.PatientInfo.FeeType.Trim()
            };

            _ctx.HospCards.Add(newCard);
            _ctx.SaveChanges();
            _cardId = newCard.CardId;

            if (setAsDefault)
            {
                SetDefault();
            }

            return new ResResult<HospCard>(Result.成功, newCard);
        }

        /// <summary>
        /// 创建就诊卡
        /// </summary>
        /// <param name="idenNo">身份证</param>
        /// <param name="name">姓名</param>
        /// <param name="phone">电话</param>
        /// <param name="address">地址</param>
        /// <param name="setAsDefault">是否设为默认卡</param>
        /// <returns></returns>
        public ResResult<HospCard> AddNewCard(string idenNo, string name, string phone, string address, bool setAsDefault)
        {
            var cardMax = ConfigurationManager.AppSettings["CardMax"].ToInt32();
            var cardCount = _ctx.HospCards
                .IsOpenId(_openId).Count(x => x.CardStatus == 1 && x.DeleteStatus == 0);
            if (cardCount >= cardMax)
            {
                return new ResResult<HospCard>(Result.失败, "最多可以添加" + cardMax + "张就诊卡!");
            }

            if (cardCount == 0)
            {
                setAsDefault = true;
            }

            var card =
               _ctx.HospCards.FirstOrDefault(x => x.CardType == 0 && x.IdenNo == idenNo && x.PatientName == name);
            if (card != null)
            {
                if (card.OpenId == _openId)
                {
                    card.DeleteStatus = 0;
                    card.CardStatus = 1;
                    card.DeleteDt = null;
                    card.AddDt = DateTime.Now;
                    card.UpdateDt = DateTime.Now;

                    _ctx.SaveChanges();
                    _cardId = card.CardId;
                }
                else
                {
                    var newExistCard = new HospCard
                    {
                        OpenId = _openId,
                        CardType = 0,
                        CardNo = card.CardNo.Trim(),
                        PatientName = card.PatientName.Trim(),
                        CardStatus = 1,
                        AddDt = DateTime.Now,
                        UpdateDt = DateTime.Now,
                        DeleteStatus = 0,
                        PatientId = card.PatientId.Trim(),
                        InDeptNo = card.InDeptNo.Trim(),
                        Name = card.Name.Trim(),
                        Gender = card.Gender.Trim(),
                        Age = card.Age.Trim(),
                        Birthdate = card.Birthdate.Trim(),
                        IdenNo = card.IdenNo.Trim(),
                        Phone = phone.Trim(),
                        FeeType = card.FeeType.Trim()
                    };

                    _ctx.HospCards.Add(newExistCard);
                    _ctx.SaveChanges();
                    _cardId = newExistCard.CardId;

                    card = newExistCard;
                }

                if (setAsDefault)
                {
                    SetDefault();
                }

                return new ResResult<HospCard>(Result.成功, card);
            }

            var createCardResult = CreateCard(idenNo, name, phone, address);
            if (createCardResult.Result == Result.未返回)
            {
                return new ResResult<HospCard>(Result.失败, "操作失败，请稍后重试");
            }
            if (createCardResult.Result == Result.失败)
            {
                return new ResResult<HospCard>(Result.失败, createCardResult.Message);
            }

            return AddBindingCard((CardType)createCardResult.Response.CardType.ToInt32(),
                createCardResult.Response.CardNo, name, setAsDefault);
        }

        /// <summary>
        /// 执行获取病人信息
        /// </summary>
        /// <param name="cardType">卡类型</param>
        /// <param name="cardNo">卡号</param>
        /// <returns></returns>
        public static ResResult<GetPatientInfoResponse> GetPatientInfo(CardType cardType, string cardNo)
        {
            var result = new ResResult<GetPatientInfoResponse>();

            //执行锁号操作
            var request = new GetPatientInfoRequest();
            request.CardNo = cardNo;
            request.CardType = cardType.ToInt32().ToString();

            GetPatientInfoResponse response;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetPatientInfo", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response = responseMsg.Content.ReadAsAsync<GetPatientInfoResponse>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内获取病人信息Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                result.Result = Result.未返回;
                return result;
            }

            result.Response = response;
            if (response.ResultCode != "0")
            {
                result.Result = Result.失败;
                result.Message = response.ResultDesc;
                return result;
            }

            result.Result = Result.成功;
            return result;
        }

        /// <summary>
        /// 执行创建就诊卡
        /// </summary>
        /// <param name="idenNo">身份证号</param>
        /// <param name="name">姓名</param>
        /// <param name="phone">电话</param>
        /// <param name="address">地址</param>
        /// <returns></returns>
        public ResResult<CreateCardResponse> CreateCard(string idenNo, string name, string phone, string address)
        {
            var result = new ResResult<CreateCardResponse>();

            var idenCard = new IdenCard(idenNo);
            if (!idenCard.IsValid())
            {
                result.Result = Result.失败;
                result.Message = "无效的身份证号码";
                return result;
            }

            var request = new CreateCardRequest();
            request.IdenNo = idenNo;
            request.Name = name;
            request.Birthdate = idenCard.GetBirthdate().ToString("yyyy-MM-dd");
            request.Gender = idenCard.GetSex();
            request.Phone = phone;
            request.Address = address;

            CreateCardResponse response;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/CreateCard", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response = responseMsg.Content.ReadAsAsync<CreateCardResponse>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内创建就诊卡Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                result.Result = Result.未返回;
                return result;
            }

            result.Response = response;

            if (response.ResultCode == "0")
            {
                result.Result = Result.成功;
                return result;
            }
            else
            {
                result.Result = Result.失败;
                result.Message = response.ResultDesc;
                return result;
            }

        }

        /// <summary>
        /// 转换数据库cardType值为界面显示卡类型名称
        /// </summary>
        /// <param name="cardType">卡类型</param>
        /// <returns></returns>
        public static string ConvertCardTypeToName(string cardType)
        {
            string cardTypeName = "未知";
            switch (cardType)
            {
                case "0":
                    cardTypeName = "诊疗卡";
                    break;
                case "1":
                    cardTypeName = "健康卡";
                    break;
                case "2":
                    cardTypeName = "市民卡";
                    break;
            }

            return cardTypeName;
        }

        public void Dispose()
        {
            _ctx.Dispose();
        }
    }

    public static class HospCardExtensions
    {
        public static IQueryable<HospCard> IsOpenId(this IQueryable<HospCard> source, string openId)
        {
            if (String.IsNullOrEmpty(openId))
            {
                return source;
            }

            return source.Where(x => x.OpenId == openId);
        }
    }

    /// <summary>
    /// 身份证
    /// </summary>
    public class IdenCard
    {
        private readonly string _id;
        private string _sex;
        private DateTime _birthdate;

        public IdenCard(string id)
        {
            _id = id;
        }

        /// <summary>
        /// 验证位身份证
        /// </summary>
        public bool IsValid()
        {
            int intLen = _id.Length;
            long n = 0;

            if (intLen == 18)
            {
                if (long.TryParse(_id.Remove(17), out n) == false || n < Math.Pow(10, 16) || long.TryParse(_id.Replace('x', '0').Replace('X', '0'), out n) == false)
                {
                    return false;//数字验证
                }
                string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";
                if (address.IndexOf(_id.Remove(2), StringComparison.Ordinal) == -1)
                {
                    return false;//省份验证
                }
                string birth = _id.Substring(6, 8).Insert(6, "-").Insert(4, "-");
                if (DateTime.TryParse(birth, out _birthdate) == false)
                {
                    return false;//生日验证
                }

                bool isMale = _id.Substring(16, 1).ToInt32().IsOdd();
                if (isMale)
                {
                    _sex = "男";
                }
                else
                {
                    _sex = "女";
                }

                string[] arrVarifyCode = ("1,0,x,9,8,7,6,5,4,3,2").Split(',');
                string[] Wi = ("7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2").Split(',');
                char[] Ai = _id.Remove(17).ToCharArray();
                int sum = 0;
                for (int i = 0; i < 17; i++)
                {
                    sum += int.Parse(Wi[i]) * int.Parse(Ai[i].ToString());
                }
                int y = -1;
                Math.DivRem(sum, 11, out y);
                if (arrVarifyCode[y] != _id.Substring(17, 1).ToLower())
                {
                    return false;//校验码验证
                }
                return true;//符合GB11643-1999标准
            }
            else if (intLen == 15)
            {
                if (long.TryParse(_id, out n) == false || n < Math.Pow(10, 14))
                {
                    return false;//数字验证
                }
                string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";
                if (address.IndexOf(_id.Remove(2), StringComparison.Ordinal) == -1)
                {
                    return false;//省份验证
                }
                string birth = _id.Substring(6, 6).Insert(4, "-").Insert(2, "-");
                if (DateTime.TryParse(birth, out _birthdate) == false)
                {
                    return false;//生日验证
                }
                return true;//符合15位身份证标准
            }
            else
            {
                return false;//位数不对
            }
        }

        public DateTime GetBirthdate()
        {
            return _birthdate;
        }

        public string GetSex()
        {
            return _sex;
        }
    }
}